package com.linktco.common.utils;


import io.swagger.annotations.ApiModelProperty;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.springblade.core.tool.utils.BeanUtil;
import org.springframework.lang.Nullable;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.util.regex.Pattern.compile;

/**
 * @author zhangnx
 */
public class U {

    public interface addValid {
    }

    public interface editValid {
    }

    public interface delValid {
    }

    @Nullable
    public static <T> T copy(@Nullable Object source, Class<T> clazz) {
        return BeanUtil.copy(source, clazz);
    }

    @Nullable
    public static <T> List<T> copy(@Nullable Collection<?> sourceList, Class<T> targetClazz) {
        return BeanUtil.copy(sourceList, targetClazz);
    }

    @SafeVarargs
    public static <T> boolean isEmpty(T... arrT) {
        return haveEmpty(arrT);
    }

    @SafeVarargs
    public static <T> boolean notEmpty(T... arrT) {
        return allNotEmpty(arrT);
    }


    @SafeVarargs
    public static <T> boolean haveEmpty(T... arrT) {
        if (allNotEmpty(arrT)) {
            return false;
        }
        return true;
    }

    @SafeVarargs
    public static <T> boolean allEmpty(T... arrT) {

        if (arrT == null) {
            return true;
        }
        if (arrT.length == 0) {
            return true;
        }

        Integer count = 0;
        for (T t : arrT) {
            if (t == null || "".equals(t.toString().trim())) {
                count += 1;
                continue;
            }

            if (t.getClass().isArray()) {
                Object[] arr = (Object[]) t;
                if (arr.length < 1) {
                    count += 1;
                    continue;
                }
            }

            if (t instanceof List) {
                List list = (List) t;
                if (list.isEmpty()) {
                    count += 1;
                }
            } else if (t instanceof Map) {
                Map map = (Map) t;
                if (map.isEmpty()) {
                    count += 1;
                }
            }
        }
        return arrT.length == count;
    }

    public static <T> boolean allNotEmpty(T... arrT) {

        if (arrT == null) {
            return false;
        }
        if (arrT.length == 0) {
            return false;
        }

        for (T t : arrT) {
            if (t == null || "".equals(t.toString().trim())) {
                return false;
            }

            if (t.getClass().isArray()) {
                try {
                    Object[] arr = (Object[]) t;
                    if (arr.length < 1) {
                        return false;
                    }
                }catch (Exception e){
                    byte[] arr1 = (byte[]) t;
                    if (arr1.length < 1) {
                        return false;
                    }
                }
            }

            if (t instanceof List) {
                List list = (List) t;
                if (list.isEmpty()) {
                    return false;
                }
            } else if (t instanceof Map) {
                Map map = (Map) t;
                if (map.isEmpty()) {
                    return false;
                }
            }
        }
        return true;
    }


    /**
     * 获取变更内容
     *
     * @param newBean 更改前的Bean
     * @param oldBean 更改后的Bean
     * @param <T>
     * @return
     */
    public static <T> Pair<String, String> getChangedFields(T newBean, T oldBean) {

        StringBuilder beforeChange = new StringBuilder();
        StringBuilder afterChange = new StringBuilder();

        Field[] fields = newBean.getClass().getDeclaredFields();

        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            field.setAccessible(true);
            try {
                Object newValue = field.get(newBean);
                Object oldValue = field.get(oldBean);
                if (Objects.equals(newValue, oldValue)) {
                    continue;
                }

                String fieldName;
                ApiModelProperty annotation = field.getAnnotation(ApiModelProperty.class);
                if (annotation == null) {
                    fieldName = field.getName();
                } else {
                    fieldName = StringUtils.isNotBlank(annotation.name()) ? annotation.name() : annotation.value();
                }

                if (oldValue != null) {
                    beforeChange.append(fieldName).append(":");
                    beforeChange.append(oldValue).append(",");
                }

                if (newValue != null) {
                    afterChange.append(fieldName).append(":");
                    afterChange.append(newValue).append(",");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        return Pair.of(beforeChange.substring(0, beforeChange.length() > 0 ? beforeChange.length() - 1 : 0),
                afterChange.substring(0, afterChange.length() > 0 ? afterChange.length() - 1 : 0));
    }


    public static Boolean haveChinese(String str) {
        Pattern p = compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        return m.find();
    }


    public static String generateSerialNo(int len) {
        String generateSource = "0123456789abcdefghigklmnopqrstuvwxyz";
        StringBuilder rtnStr = new StringBuilder();
        for (int i = 0; i < len; i++) {
            String nowStr = String.valueOf(generateSource.charAt((int) Math.floor(Math.random() * generateSource.length())));
            rtnStr.append(nowStr);
            generateSource = generateSource.replaceAll(nowStr, "");
        }
        return rtnStr.toString();
    }

    public static String reverse(String s) {
        return new StringBuilder(s).reverse().toString();
    }
}
